from typing import Optional
from fastapi import APIRouter, Depends, UploadFile, File, Form, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession

from app.api import deps
from app.core.logging_config import get_logger
from app.models import User
from app.schemas.base import UnifiedResponse, success_response
from app.services.capsule_service import capsule_service

router = APIRouter()
logger = get_logger(__name__)


@router.post("/upload", response_model=UnifiedResponse)
async def upload_report(
    file: UploadFile = File(..., description="上传的报告文件"),
    report_type: str = Form(..., description="报告类型，例如：血常规报告"),
    owner: str = Form(..., description="报告所属者的UUID"),
    collector: str = Form(..., description="采集机构，例如：省三甲医院血检科"),
    collector_time: str = Form(..., description="采集时间，格式：2025-09-30 14:50:26"),
    signature: str = Form(default="1111111111", description="签名"),
    db: AsyncSession = Depends(deps.get_db),
    current_user: User = Depends(deps.get_current_user)
):
    """
    上传报告到胶囊系统

    该接口会自动处理鉴权流程：
    1. 从缓存获取或重新申请access_token
    2. 使用token上传报告
    3. 如果鉴权失败，自动刷新token并重试

    参数：
    - **file**: 报告文件（支持Excel等格式）
    - **report_type**: 报告类型（如：血常规报告、尿常规报告等）
    - **owner**: 报告所属者的UUID
    - **collector**: 采集机构名称
    - **collector_time**: 采集时间（格式：YYYY-MM-DD HH:MM:SS）
    - **signature**: 签名（可选，默认：1111111111）

    返回：
    - 胶囊系统的响应结果
    """
    try:
        # 验证文件
        if not file.filename:
            raise HTTPException(status_code=400, detail="No file provided")

        # 构建props参数
        props = {
            "type": report_type,
            "owner": owner,
            "collector": collector,
            "collector_time": collector_time
        }

        logger.info(f"Uploading report: {file.filename}, type: {report_type}, owner: {owner}")

        # 调用胶囊服务上传报告
        result = await capsule_service.upload_report(
            file=file,
            props=props,
            signature=signature
        )

        logger.info(f"Report uploaded successfully: {file.filename}")

        return success_response(
            data=result,
            msg="报告上传成功"
        )

    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Failed to upload report: {e}")
        raise HTTPException(status_code=500, detail=f"上传报告失败: {str(e)}")


@router.get("/acl/status", response_model=UnifiedResponse)
async def get_acl_status(
    current_user: User = Depends(deps.get_current_user)
):
    """
    获取ACL鉴权状态

    返回当前ACL和access token的缓存状态
    """
    try:
        from app.utils.redis_client import redis_client

        # 检查ACL secret缓存
        acl_secret = await redis_client.get(capsule_service.ACL_SECRET_KEY)
        acl_cached = acl_secret is not None

        # 检查access token缓存
        access_token = await redis_client.get(capsule_service.ACCESS_TOKEN_KEY)
        token_cached = access_token is not None

        # 获取token过期时间
        expire_time = await redis_client.get(capsule_service.TOKEN_EXPIRE_KEY)

        status = {
            "acl_cached": acl_cached,
            "token_cached": token_cached,
            "token_expire_time": expire_time,
            "base_url": capsule_service.base_url,
            "tenant_id": capsule_service.tenant_id
        }

        return success_response(
            data=status,
            msg="ACL状态查询成功"
        )

    except Exception as e:
        logger.error(f"Failed to get ACL status: {e}")
        raise HTTPException(status_code=500, detail=f"获取状态失败: {str(e)}")


@router.post("/acl/refresh", response_model=UnifiedResponse)
async def refresh_acl(
    current_user: User = Depends(deps.get_current_user)
):
    """
    刷新ACL和access token

    强制重新获取ACL和access token，更新缓存
    """
    try:
        logger.info("Manually refreshing ACL and access token")

        # 强制刷新access token（会自动刷新ACL）
        access_token = await capsule_service.get_access_token(force_refresh=True)

        return success_response(
            data={"token_refreshed": True},
            msg="ACL和Token刷新成功"
        )

    except Exception as e:
        logger.error(f"Failed to refresh ACL: {e}")
        raise HTTPException(status_code=500, detail=f"刷新失败: {str(e)}")
